package cn.acyou.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

/**
 * @author fangyou
 * @version [1.0.0, 2021-08-04 14:07]
 */
public class CommonCache {
    /**
     * 内部缓存池
     */
    public static final ConcurrentHashMap<String, String> CACHE_MAP = new ConcurrentHashMap<>();
    /**
     * 内部缓存池(Obj)
     */
    public static final Map<String, Object> OBJ_CACHE_MAP = new HashMap<>();
    /**
     * 日志
     */
    public static final List<String> LOG = new ArrayList<>();


    public static void addLog(String text) {
        LOG.add(text);
    }

    public static void addExceptionLog(Exception e) {
        ByteArrayOutputStream buf = new ByteArrayOutputStream();
        e.printStackTrace(new PrintWriter(buf, true));
        try {
            buf.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        LOG.add("Exception:" + buf.toString());
    }

    /**
     * 内部缓存池取并缓存
     */
    @SuppressWarnings("unchecked")
    public static <T> T getAndCacheObj(String key, Function<String, Object> function){
        Object o = OBJ_CACHE_MAP.get(key);
        if (o != null) {
            return (T) o;
        }
        Object apply = function.apply(key);
        OBJ_CACHE_MAP.put(key, apply);
        return (T) apply;
    }

    /**
     * 获取缓存值
     *
     * @param key 缓存Key
     * @return 缓存value
     */
    public static String get(String key) {
        return CACHE_MAP.get(key);
    }

    /**
     * 设置缓存值
     *
     * @param key   缓存Key
     * @param value 缓存value
     */
    public static void put(String key, String value) {
        CACHE_MAP.put(key, value);
    }


    /**
     * 获取和缓存
     *
     * @param key      关键
     * @param function 函数
     * @return {@link String}
     */
    public static String getAndCache(String key, Function<String, String> function) {
        String v = get(key);
        if (v != null && v.length() > 0) {
            return v;
        }
        String value = function.apply(key);
        put(key, value);
        return value;
    }

    /**
     * 清除缓存
     */
    public static void clearAllCache() {
        CACHE_MAP.clear();
        OBJ_CACHE_MAP.clear();
    }


    /**
     * 清除缓存
     */
    public static void clearCache(List<String> keys) {
        keys.forEach(CACHE_MAP::remove);
        keys.forEach(OBJ_CACHE_MAP::remove);
    }

    /**
     * 获取项目统计
     *
     * @return int
     */
    public static int getItemCount() {
        return CACHE_MAP.size() + OBJ_CACHE_MAP.size();
    }
}
